using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using QiHe.CodeLib;
using QiHe.CodeGen;

namespace QiHe.ReliableData
{
    public partial class GenCodeDialog : Form
    {
        public GenCodeDialog()
        {
            InitializeComponent();
            LoadSettings();
        }

        private void LoadSettings()
        {
            Settings.Default.Set(textBoxNamespace, "Text", "Namespace");
            Settings.Default.Set(folderBrowserCode, "FolderPath", "CodeFolder");
            Settings.Default.Set(folderBrowserData, "FolderPath", "DataFolder");
        }

        public Package Package;

        string NamespaceName
        {
            get { return textBoxNamespace.Text; }
        }

        private void buttonGen_Click(object sender, EventArgs e)
        {
            string codeFolder = folderBrowserCode.FolderPath;
            FileHelper.CreateDirectoryIfNotExist(codeFolder);
            foreach (DataType dataType in Package.DataTypes)
            {
                GenDataTypeCode(dataType, codeFolder);
            }
            foreach (EnumType enumType in Package.EnumTypes)
            {
                GenEnumTypeCode(enumType, codeFolder);
            }
            string dataFolder = folderBrowserData.FolderPath;
            if (dataFolder != "")
            {
                FileHelper.CreateDirectoryIfNotExist(dataFolder);
                foreach (object data in Package.DataObjects)
                {
                    string name = TypeHelper.TryGetName(data);
                    string xmlfile = Path.Combine(dataFolder, name + ".xml");
                    XmlSerialization.Serialize(xmlfile, data);
                }
            }
        }

        private void GenDataTypeCode(DataType dataType, string path)
        {
            string file = Path.Combine(path, dataType.Name + ".cs");
            CodeWriter writer = new CodeWriter(file);

            Namespace ns = new Namespace(NamespaceName);
            ns.Usings.Add("System.Xml.Serialization");
            ns.AddClass(BuildClass(dataType));
            ns.Output(writer);
            writer.Close();
        }

        private void GenEnumTypeCode(EnumType enumType, string path)
        {
            string file = Path.Combine(path, enumType.Name + ".cs");
            CodeWriter writer = new CodeWriter(file);

            Namespace ns = new Namespace(NamespaceName);
            ns.Classes.Add(BuildEnum(enumType));
            ns.Output(writer);
            writer.Close();
        }

        private Class BuildClass(DataType dataType)
        {
            Class dataTypeClass = new Class(dataType.Name);
            dataTypeClass.Modifiers.Add("public");
            dataTypeClass.Modifiers.Add("partial");

            foreach (TypeField typeField in dataType.Fields)
            {
                Field field = new Field(typeField.FieldType, typeField.Name);
                field.Modifiers.Add("public");
                if (typeField.XmlSerialize != null)
                {
                    if (typeField.XmlSerialize == "XmlElement" && TypeHelper.IsListType(typeField.FieldType))
                    {
                        field.Attributes.Add("XmlElement(\"" + TypeHelper.GetItemType(typeField.FieldType) + "\")");
                    }
                    else
                    {
                        field.Attributes.Add(typeField.XmlSerialize);
                    }
                }
                else if (typeField.FieldType == "List<string>")
                {
                    field.Attributes.Add("XmlArrayItem(\"String\")");
                }
                dataTypeClass.Members.Add(field);
            }

            return dataTypeClass;
        }

        private QiHe.CodeGen.Enum BuildEnum(EnumType enumType)
        {
            QiHe.CodeGen.Enum enumTypeClass = new QiHe.CodeGen.Enum(enumType.Name);

            if (enumType.IsFlags)
            {
                enumTypeClass.Attributes.Add("Flags");
            }

            foreach (EnumValue enumValue in enumType.Values)
            {
                enumTypeClass.Values.Add(String.Format("{0} = {1}", enumValue.Name, enumValue.Value));
            }

            return enumTypeClass;
        }
    }
}